package com.linkwin.updater;

import android.content.Context;
import android.content.DialogInterface;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;

import com.google.gson.Gson;
import com.linkwin.updater.bean.VersionBean;
import com.linkwin.updater.callback.AppUpdateCallback;
import com.linkwin.updater.callback.UpdateCallback;
import com.linkwin.updater.dialog.AppDialog;
import com.linkwin.updater.dialog.AppDialogConfig;
import com.linkwin.updater.http.OkHttpManager;
import com.linkwin.updater.util.TimeCheckUtil;

import java.io.File;
import java.io.IOException;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Application app check manager
 */
public class AppCheck {

    private Context mContext;
    private boolean showTip;
    private boolean updateOnTime;

    private AppUpdater mAppUpdater;

    private String mCheckURL = "";
    private String mDownloadURL = "";
    private UpdaterStyle mStyle; // 版本升级样式

    private Thread checkThread;

    private TextView tvProgress;
    private ProgressBar progressBar;
    private Toast toast;
    private final Object mLock = new Object();
    private UpdateCallback updateCallback;
    private AppUpdateCallback updateBannerCallback; // 系统横幅效果
    private VersionBean versionBean;

    private static final int NO_PROJECT = 0; // 项目不存在
    private static final int NEW_VERSION = 1; // 发现新版本
    private static final int NO_NEW_VERSION = 2; // 当前版本已是最新版本
    private static final int NEW_VERSION_IGNORE = 3; // 发现新版本,但暂不在约定时间内，暂不提示更新

    public AppCheck(Context context, String checkURL, String downloadURL) {
        init(context, checkURL, downloadURL, UpdaterStyle.CUSTOM_CALLBACK, false, false);
    }

    public AppCheck(Context context, String checkURL, String downloadURL, boolean showTip) {
        init(context, checkURL, downloadURL, UpdaterStyle.CUSTOM_CALLBACK, showTip, false);
    }

    public AppCheck(Context context, String checkURL, String downloadURL, UpdaterStyle style, boolean showTip) {
        init(context, checkURL, downloadURL, style, showTip, false);
    }

    public AppCheck(Context context, String checkURL, String downloadURL, UpdaterStyle style, boolean showTip, boolean updateOnTime) {
        init(context, checkURL, downloadURL, style, showTip, updateOnTime);
    }

    private void init(Context context, String checkURL, String downloadURL, UpdaterStyle style, boolean showTip, boolean updateOnTime) {
        this.mContext = context;
        this.showTip = showTip;
        this.updateOnTime = updateOnTime;
        this.mCheckURL = checkURL;
        this.mDownloadURL = downloadURL;

        if (!TextUtils.isEmpty(checkURL)) { // 如果有版本检查的接口，不允许直接下载 默认样式为 CUSTOM_CALLBACK
            switch (style) {
                case ONE_KEY_BANNER:
                case ONE_KEY_BACKEND:
                case ONE_KEY_CALLBACK:
                    this.mStyle = UpdaterStyle.CUSTOM_CALLBACK;
                    break;
                default:
                    this.mStyle = style;
                    break;
            }
        } else {
            // 如果没有版本检查的接口，则直接下载，默认样式为 ONE_KEY_CALLBACK
            switch (style) {
                case ALERT_CALLBACK:
                case DIALOG_CALLBACK:
                case CUSTOM_CALLBACK:
                    this.mStyle = UpdaterStyle.ONE_KEY_CALLBACK;
                    break;
                default:
                    this.mStyle = style;
                    break;
            }
        }

        this.updateCallback = new UpdateCallback() {

            @Override
            public void onDownloading(boolean isDownloading) {
                if (isDownloading) {
                    showToast(mContext.getString(R.string.app_updater_repeat_download));
                } else {
                    View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_updater_progress, null);
                    tvProgress = view.findViewById(R.id.tvProgress);
                    progressBar = view.findViewById(R.id.progressBar);
                    AppDialog.INSTANCE.showDialog(mContext, view, false);
                }
            }

            @Override
            public void onStart(String url) {

            }

            @Override
            public void onProgress(long progress, long total, boolean isChanged) {
                if (isChanged) {
                    updateProgress(progress, total);
                }
            }

            @Override
            public void onFinish(File file) {
                AppDialog.INSTANCE.dismissDialog();
                showToast(mContext.getString(R.string.app_updater_finish_notification_title));
            }

            @Override
            public void onError(Exception e) {
                AppDialog.INSTANCE.dismissDialog();
                showToast(mContext.getString(R.string.app_updater_error_notification_title));
            }

            @Override
            public void onCancel() {
                AppDialog.INSTANCE.dismissDialog();
                showToast(mContext.getString(R.string.app_updater_cancel_notification_title));
            }
        };

        this.updateBannerCallback = new AppUpdateCallback() {
            @Override
            public void onStart(String url) {
                super.onStart(url);
                // 模仿系统自带的横幅通知效果
                AppDialogConfig config = new AppDialogConfig(mContext, R.layout.dialog_updater_heads_up);
                config.setStyleId(R.style.app_dialog_heads_up)
                        .setWidthRatio(.95f)
                        .setGravity(Gravity.TOP);
                AppDialog.INSTANCE.showDialog(mContext, config);
                new CountDownTimer(2000, 500) {

                    @Override
                    public void onTick(long millisUntilFinished) {

                    }

                    @Override
                    public void onFinish() {
                        AppDialog.INSTANCE.dismissDialog();
                    }
                }.start();
            }

            @Override
            public void onProgress(long progress, long total, boolean isChanged) {

            }

            @Override
            public void onFinish(File file) {
                showToast(mContext.getString(R.string.app_updater_finish_notification_title));
            }
        };
    }

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            versionBean = (VersionBean) msg.obj;
            switch (msg.what) {
                case NO_NEW_VERSION:
                case NO_PROJECT:
                    if (showTip) {
                        showToast(((VersionBean) msg.obj).getMessage());
                    }
                    break;
                case NEW_VERSION_IGNORE:
                    // 不做任何处理
                    break;

                case NEW_VERSION:
                    String versionStr = "";
                    if (versionBean != null && versionBean.getData() != null && !TextUtils.isEmpty(versionBean.getData().getVersion())) {
                        versionStr = versionBean.getData().getVersion();
                    }

                    String descStr;
                    if (versionBean != null && versionBean.getData() != null && !TextUtils.isEmpty(versionBean.getData().getVersionDesc())) {
                        descStr = versionBean.getData().getVersionDesc();
                    } else {
                        descStr = mContext.getString(R.string.app_updater_default_desc);
                    }

                    boolean isForced;
                    if (versionBean != null && versionBean.getData() != null) {
                        isForced = (1 == versionBean.getData().getIsForcedUpdate());
                    } else {
                        isForced = false;
                    }

                    // 执行新版本下载操作。提供多种样式
                    switch (mStyle) {
                        case ONE_KEY_BACKEND:
                            updateStyle0();
                            break;
                        case ONE_KEY_BANNER:
                            updateStyle1();
                            break;
                        case ONE_KEY_CALLBACK:
                            updateStyle2();
                            break;
                        case ALERT_CALLBACK:
                            updateStyle3(versionStr, descStr, !isForced);
                            break;
                        case DIALOG_CALLBACK:
                            updateStyle4(versionStr, descStr, !isForced);
                            break;
                        case CUSTOM_CALLBACK:
                            updateStyle5(versionStr, descStr, !isForced);
                            break;
                    }
                    break;
            }
            return false;
        }
    });

    private void updateProgress(long progress, long total) {
        if (tvProgress == null || progressBar == null) {
            return;
        }
        if (progress > 0) {
            int currProgress = (int) (progress * 1.0f / total * 100.0f);
            tvProgress.setText(mContext.getString(R.string.app_updater_progress_notification_content) + currProgress + "%");
            progressBar.setProgress(currProgress);
        } else {
            tvProgress.setText(mContext.getString(R.string.app_updater_start_notification_content));
        }

    }

    public void checkNewVersion() {
        // 如果检查接口为空，直接下载
        if (TextUtils.isEmpty(mCheckURL)) {
            if (!TextUtils.isEmpty(mDownloadURL)) { // 下载接口不为空，执行下载任务
                switch (mStyle) {
                    case ONE_KEY_BACKEND:
                        updateStyle0();
                        break;
                    case ONE_KEY_BANNER:
                        updateStyle1();
                        break;
                    case ONE_KEY_CALLBACK:
                        updateStyle2();
                        break;
                    default:
                        break;
                }
            } else { // 下载接口为空,直接当无项目处理
                dealAsNoProject();
            }
        } else {  // 如果检查接口不为空，检查
            if (TextUtils.isEmpty(mDownloadURL)) { // 下载接口为空,直接当无项目处理
                dealAsNoProject();
            } else {
                checkThread = new Thread(mCheckRunnable);
                checkThread.start();
            }
        }
    }

    /**
     * 条件不符合，或者有报错时，当做无项目处理
     */
    private void dealAsNoProject() {
        VersionBean bean = new VersionBean();
        bean.setTotal(0);
        bean.setData(null);
        bean.setTag(0);
        bean.setMessage(mContext.getString(R.string.app_updater_no_project));
        mHandler.sendMessage(Message.obtain(mHandler, NO_PROJECT, bean));
    }

    private Runnable mCheckRunnable = new Runnable() {
        public void run() {
            OkHttpClient client = new OkHttpClient();
            // 创建请求对象
            Request request = new Request.Builder()
                    .url(mCheckURL)
                    .build();
            try {
                // 发送请求并获取响应
                Response response = client.newCall(request).execute();
                // 解析响应数据
                ResponseBody responseBody = response.body();
                if (responseBody != null) {
                    String jsonData = responseBody.string();
                    VersionBean bean = new Gson().fromJson(jsonData, VersionBean.class);
                    // 在系统配置的时间范围内才执行更新操作
                    if (1 == bean.getTag()) {
                        if (updateOnTime) {
                            String startTime = "00:00", endTime = "23:59";
                            if (bean.getData() != null && !TextUtils.isEmpty(bean.getData().getStartTime())) {
                                startTime = bean.getData().getStartTime();
                            }
                            if (bean.getData() != null && !TextUtils.isEmpty(bean.getData().getEndTime())) {
                                endTime = bean.getData().getEndTime();
                            }
                            String[] splitStart = startTime.split(":");
                            String[] splitEnd = endTime.split(":");

                            if (TimeCheckUtil.isTimeInRange(Integer.parseInt(splitStart[0]), Integer.parseInt(splitStart[1]), Integer.parseInt(splitEnd[0]), Integer.parseInt(splitEnd[1]))) {
                                mHandler.sendMessage(Message.obtain(mHandler, NEW_VERSION, bean));
                            } else {
                                mHandler.sendMessage(Message.obtain(mHandler, NEW_VERSION_IGNORE, bean));
                            }
                        } else {
                            mHandler.sendMessage(Message.obtain(mHandler, NEW_VERSION, bean));
                        }
                    } else {
                        mHandler.sendMessage(Message.obtain(mHandler, NO_NEW_VERSION, bean));
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                dealAsNoProject();
            }
        }
    };


    /**
     * 简单一键后台升级
     */
    private void updateStyle0() {
        mAppUpdater = new AppUpdater(mContext, mDownloadURL);
        mAppUpdater.start();
    }


    /**
     * 一键下载并横幅样式监听
     */
    private void updateStyle1() {
        UpdateConfig config = new UpdateConfig();
        config.setUrl(mDownloadURL);
        mAppUpdater = new AppUpdater(mContext, config)
                .setHttpManager(OkHttpManager.getInstance())
                .setUpdateCallback(updateBannerCallback);
        mAppUpdater.start();
    }

    /**
     * 一键下载并监听
     */
    private void updateStyle2() {
        mAppUpdater = new AppUpdater.Builder(mContext)
                .setUrl(mDownloadURL)
                .setSupportCancelDownload(true)
                .build()
                .setUpdateCallback(updateCallback);
        mAppUpdater.start();
    }

    /**
     * 1.显示下载框
     * 2.隐藏确认框
     */
    private void justDownload() {
        mAppUpdater = new AppUpdater(mContext, mDownloadURL);
        mAppUpdater.setNotification(null); // 仅下载，不通过Notification显示进度条
        mAppUpdater.setUpdateCallback(updateCallback).start();
        AppDialog.INSTANCE.dismissDialog();
    }

    /**
     * 系统弹框升级
     */
    private void updateStyle3(String versionStr, String descStr, boolean isCancel) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
                .setTitle(String.format("%s ( %s )", mContext.getString(R.string.app_dialog_title), versionStr))
                .setMessage(descStr)
                .setPositiveButton(mContext.getString(R.string.app_dialog_upgrade), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        justDownload();
                    }
                })
                .setCancelable(isCancel);

        if (isCancel) {
            builder.setNegativeButton(mContext.getString(R.string.app_dialog_ignore), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    AppDialog.INSTANCE.dismissDialog();
                }
            });
        }

        builder.show();
    }

    /**
     * 简单弹框升级
     */
    private void updateStyle4(String versionStr, String descStr, boolean isCancel) {
        AppDialogConfig config = new AppDialogConfig(mContext);
        config.setTitle(String.format("%s ( %s )", mContext.getString(R.string.app_dialog_title), versionStr))
                .setConfirm(mContext.getString(R.string.app_dialog_upgrade))
                .setCancel(mContext.getString(R.string.app_dialog_ignore))
                .setContent(descStr)
                .setHideCancel(!isCancel)
                .setOnClickCancel(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AppDialog.INSTANCE.dismissDialog();
                    }
                })
                .setOnClickConfirm(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        justDownload();
                    }
                });
        AppDialog.INSTANCE.showDialog(config, isCancel);
    }

    /**
     * 自定义弹框
     */
    private void updateStyle5(String versionStr, String descStr, boolean isCancel) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_updater_custom, null);

        TextView tvTitle = view.findViewById(R.id.tvTitle);
        tvTitle.setText(String.format("%s ( %s )", mContext.getString(R.string.app_dialog_title), versionStr));
        TextView tvContent = view.findViewById(R.id.tvContent);
        tvContent.setText(descStr);

        View btnCancel = view.findViewById(R.id.btnCancel);
        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AppDialog.INSTANCE.dismissDialog();
            }
        });
        if (isCancel) {
            btnCancel.setVisibility(View.VISIBLE);
        } else {
            btnCancel.setVisibility(View.GONE);
        }
        View btnConfirm = view.findViewById(R.id.btnConfirm);
        btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                justDownload();
            }
        });

        AppDialog.INSTANCE.showDialog(mContext, view, isCancel);
    }


    public void showToast(String text) {
        if (toast == null) {
            synchronized (mLock) {
                if (toast == null) {
                    toast = Toast.makeText(mContext, text, Toast.LENGTH_SHORT);
                }
            }
        }
        toast.setText(text);
        toast.show();
    }
}
